import os
import math
import shutil
import random
import functools
import os.path as path
import random_word as rw
import Source.precondition as pre


def cmpName(s1: str, s2: str) -> int:
    for c1, c2 in zip(s1, s2):
        if c1 < c2:
            return -1
        elif c1 > c2:
            return 1
    return 0 if len(s1) == len(s2) else -1 if len(s1) < len(s2) else 1


def fileSolution(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        """
        Create test files for chapter7
        :return:
        """

        def writeLines(fileObj, strIterator):
            fileObj.write("\n".join(strIterator))

        def removeIfExists(filePath: str):
            if path.exists(filePath):
                os.remove(filePath)

        generator = rw.RandomWords()

        if func.__name__ == copyFile.__name__:
            filename = "copy.txt"
            removeIfExists(filename)
            with open(filename, "w", encoding="utf-8") as file:
                file.write("test")
            print(filename + " created")

        elif func.__name__ == statistics.__name__:
            filename = "Numbers.txt"
            removeIfExists(filename)
            with open(filename, "w", encoding="utf-8") as file:
                writeLines(file, map(str, (random.uniform(0, 100) for _ in range(50))))
            print(filename + " created")

        elif func.__name__ == mergeFiles.__name__:
            filename = "folder"
            if path.exists(filename):
                shutil.rmtree(filename)
            os.mkdir(filename)
            for i in range(4):
                with open("%s/file%d" % (filename, i + 1), "w", encoding="utf-8") as file:
                    file.write("test%d" % (i + 1))
            print(filename + " created")

        elif func.__name__ == removeWords.__name__:
            filename = "word.txt"
            words = generator.get_random_words(limit=20)
            removeIfExists("word.txt")
            with open(filename, "w", encoding="utf-8") as file:
                writeLines(file, words)
            print(filename + " created")

        elif func.__name__ == insertName.__name__:
            filename = "Names.txt"
            words = generator.get_random_words(limit=20)
            words.sort(key=functools.cmp_to_key(cmpName))
            removeIfExists(filename)
            with open(filename, "w", encoding="utf-8") as file:
                writeLines(file, words)
            print(filename + " created")

        elif func.__name__ == printSpecifiedLine.__name__:
            filename = "largefile.txt"
            removeIfExists(filename)
            lines = []
            for i in range(5):
                words = generator.get_random_words(limit=random.randint(1, 10))
                line = ",".join(words)
                lines.append(line)
            with open(filename, "w", encoding="utf-8") as file:
                writeLines(file, lines)
            print(filename + " created")

        return func(*args, **kwargs)

    return wrapper


@fileSolution
def copyFile():
    """
    54
    """
    shutil.copy("copy.txt", "new.txt")


@fileSolution
def statistics():
    """
    55
    """
    with open("Numbers.txt") as file:
        numbers = [float(line[:-1]) for line in file.readlines()]
    numbers.sort()
    avg = sum(numbers) / len(numbers)
    variance = sum(((num - avg) ** 2 for num in numbers)) / len(numbers)
    sd = math.sqrt(variance)
    with open("Sort.txt", "w") as file:
        file.writelines((str(number) + "\n") for number in numbers)
        file.write("%f\n%f\n%f" % (avg, variance, sd))


@fileSolution
def mergeFiles():
    lst = []
    for i in range(1, 5):
        with open("folder/file%d" % i) as file:
            lst.append(file.read())
    content = "".join(lst)
    with open("merge.txt", "w") as file:
        file.write(content)


@fileSolution
def removeWords():
    with open("word.txt") as file:
        lines = file.readlines()
        lines = [word for word in lines if word[0] not in ['a', 'i', 'u', 'e', 'o']]
    with open("new_word.txt", "w", encoding="utf-8") as file:
        file.writelines(lines)


@fileSolution
def insertName():
    newName = "Abbot"
    with open("Names.txt", "r+") as file:
        names = file.readlines()
        index = 0
        for i in range(len(names)):
            index = i
            if cmpName(names[i], newName) == 1:
                break
        names.insert(index, newName + "\n")
        file.seek(0)
        file.writelines(names)


@fileSolution
def printSpecifiedLine():
    pos = 0
    indexes = []
    with open("largefile.txt") as file:
        while pos < path.getsize("largefile.txt") - 1:
            indexes.append(pos)
            content = file.readline()
            pos = file.tell()
        index = eval(input("请输入需要读取的行号(1~%d)：" % len(indexes)))

        pre.isTrue(type(index) == int and 0 < index <= len(indexes))

        file.seek(indexes[index - 1])
        content = file.readline()
        print(content.rstrip("\n"))
